package org.dcarew.clearcase;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILightweightLabelDecorator;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.ui.TeamUI;

/**
 *  
 * 
 * @author Devon Carew
 */
public class CCLabelDecorator
    extends LabelProvider
    implements ILightweightLabelDecorator, IPropertyChangeListener, IResourceChangeListener
{
    public static final String DECORATOR_ID = "org.dcarew.clearcase.labelDecorator";
    
    static ImageDescriptor VERSIONED = CCPlugin.getImageDescriptor("ovr/version_controlled.gif");
    static ImageDescriptor CHECKED_OUT = CCPlugin.getImageDescriptor("ovr/checkedout_ov.gif");
    static ImageDescriptor DIRTY = CCPlugin.getImageDescriptor("ovr/dirty_ov.gif");
    static ImageDescriptor ADDED = CCPlugin.getImageDescriptor("ovr/added_ov.gif");
    static ImageDescriptor DELETED = CCPlugin.getImageDescriptor("ovr/del_stat.gif");
    static ImageDescriptor ERRORED = CCPlugin.getImageDescriptor("ovr/failed_ovr.gif");
    static ImageDescriptor UNKNOWN = CCPlugin.getImageDescriptor("ovr/question_ov.gif");
    
    
    /**
     * 
     */
    public CCLabelDecorator()
    {
        TeamUI.addPropertyChangeListener(this);
        ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
    }




    @Override
    public void decorate(Object element, IDecoration decoration)
    {
        if (!(element instanceof IResource))
            return;
        
        IResource resource = (IResource)element;
        
        IProject project = resource.getProject();
        
        if (!CCRepositoryProvider.isClearCaseRepository(project))
            return;
        
        CCRepositoryProvider provider = (CCRepositoryProvider)
            RepositoryProvider.getProvider(project, CCRepositoryProvider.PROVIDER_ID);
        
        if (resource.isDerived() || resource.isTeamPrivateMember())
            return;
        
        if (resource instanceof IProject)
        {
            String viewName = provider.getViewName(project);
            
            CCSyncInfo syncInfo = provider.getSyncInfoRecursive(project);
            
            decorateProject(project, syncInfo, viewName, decoration);
        }
        else if (resource instanceof IFolder)
        {
            IFolder folder = (IFolder)resource;
            
            CCSyncInfo syncInfo = provider.getSyncInfoRecursive(folder);
            
            decorateFolder(folder, syncInfo, decoration);
        }
        else if (resource instanceof IFile)
        {
            CCSyncInfo syncInfo = provider.getSyncInfo(resource);
            
            decorateFile((IFile)resource, syncInfo, decoration);
        }
    }




    private void decorateProject(IProject resource, CCSyncInfo syncInfo,
            String viewName, IDecoration decoration)
    {
        if (viewName != null)
            decoration.addSuffix(" [" + viewName + "]");
        else
            decoration.addSuffix(" [ClearCase]");
        
        decorateFolder(resource, syncInfo, decoration);
    }




    private void decorateFolder(IContainer resource, CCSyncInfo syncInfo, IDecoration decoration)
    {
        if (syncInfo.isUnknown())
            decoration.addOverlay(UNKNOWN);
        else if (syncInfo.isDirty())
            decoration.addOverlay(DIRTY);
        else if (syncInfo.isCheckedOut())
            decoration.addOverlay(CHECKED_OUT);
        else if (syncInfo.isAdded())
            decoration.addOverlay(ADDED);
        else if (syncInfo.isDeleted())
            decoration.addOverlay(DELETED);
        else if (syncInfo.isUnderRevisionControl())
            decoration.addOverlay(VERSIONED);
    }




    private void decorateFile(IFile resource, CCSyncInfo syncInfo, IDecoration decoration)
    {
        if (syncInfo == null)
            return;
        
        if (!syncInfo.isUnderRevisionControl())
            decoration.addOverlay(UNKNOWN);
        else if (syncInfo.isCheckedOut())
            decoration.addOverlay(CHECKED_OUT);
        else if (syncInfo.isDirty())
            decoration.addOverlay(DIRTY);
        else if (syncInfo.isAdded())
            decoration.addOverlay(ADDED);
        else if (syncInfo.isDeleted())
            decoration.addOverlay(DELETED);
        else if (syncInfo.isUnderRevisionControl())
            decoration.addOverlay(VERSIONED);
    }




    @Override
    public void dispose()
    {
        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
        TeamUI.removePropertyChangeListener(this);
        
        super.dispose();
    }




    @Override
    public void propertyChange(PropertyChangeEvent event)
    {
        if (isEventOfInterest(event))
        {
            refresh();
        }   
    }
    
    
    private boolean isEventOfInterest(PropertyChangeEvent event)
    {
        String prop = event.getProperty();
        
        return prop.equals(TeamUI.GLOBAL_IGNORES_CHANGED) 
            || prop.equals(TeamUI.GLOBAL_FILE_TYPES_CHANGED);
    }
    
//    /**
//     * Post the label event to the UI thread
//     *
//     * @param events  the events to post
//     */
//    private void postLabelEvent(final LabelProviderChangedEvent event) {
//        Display.getDefault().asyncExec(new Runnable() {
//            public void run() {
//                fireLabelProviderChanged(event);
//            }
//        });
//    }

    /*
     * Perform a blanket refresh of all decorations
     */
     public static void refresh()
     {
         CCPlugin.getPlugin().getWorkbench().getDecoratorManager().update(DECORATOR_ID);
     }


    // IResourceChangeListener interface

    @Override
    public void resourceChanged(IResourceChangeEvent event)
    {
        // TODO: optimize this -
        
        Display.getDefault().asyncExec(new Runnable() {
            @Override
            public void run() {
                refresh();
            }
        });
    }
    
//    /*
//     * Update the decorators for every resource in project
//     */
//    private void refresh(IProject project)
//    {
//        final List<IResource> resources = new ArrayList<IResource>();
//        
//        try
//        {
//            project.accept(new IResourceVisitor() {
//                public boolean visit(IResource resource) {
//                    resources.add(resource);
//                    
//                    return true;
//                }
//            });
//            
//            postLabelEvent(new LabelProviderChangedEvent(this, resources.toArray()));
//        }
//        catch (CoreException e)
//        {
//            // TODO:
//            
//            e.printStackTrace();
//        }
//    }
    
}
